package com.seng.resourcetycoon.manager;

import com.seng.resourcetycoon.core.entities.GameConfiguration;
import com.seng.resourcetycoon.core.enums.DifficultyLevel;
import com.seng.resourcetycoon.core.enums.TowerState;
import com.seng.resourcetycoon.gui.models.PlayerInfo;
import com.seng.resourcetycoon.gui.models.ResourceTower;
import com.seng.resourcetycoon.gui.models.Upgrade;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

public class GameEnvironment {

    private final PlayerInfo playerInfo;

    private Integer gameRound = 1;

    private GameConfiguration gameConfiguration;

    private List<ResourceTower> allTower;
    private final List<Upgrade> upgrades = new ArrayList<>();

    private static final GameEnvironment gameEnvironment = new GameEnvironment();

    public static GameEnvironment getInstance(){
        return gameEnvironment;
    }

    private GameEnvironment(){
        allTower = new CopyOnWriteArrayList<>();
        playerInfo = new PlayerInfo();
    }

    public void addCoin(BigDecimal bigDecimal){
        playerInfo.addCoin(bigDecimal);
    }

    public void rewardPlayerOnRoundEnd(){
        DifficultyLevel difficultyLevel = gameConfiguration.getDifficultyLevel();
        int baseReward = 100; // 基础金币奖励
        int difficultyFactor = difficultyLevel.getPointMultiplier(); // 难度系数
        int roundNumber = gameRound; // 当前游戏轮次

        // 计算总奖励并添加给玩家
        int totalReward = baseReward * difficultyFactor * roundNumber;
        addCoin(BigDecimal.valueOf(totalReward));
    }

    public void subtractCoin(BigDecimal bigDecimal){
        playerInfo.subtractCoin( bigDecimal);
    }

    public void addTower(ResourceTower tower) {
        allTower.add(tower);
    }

    public void removeTower(ResourceTower tower) {
        allTower.remove(tower);
    }

    public void addUpgrade(Upgrade upgrade) {
        upgrades.add(upgrade);
    }

    public void removeUpgrade(Upgrade upgrade) {
        upgrades.remove(upgrade);
    }

    public BigDecimal getCoin(){
        if(playerInfo.getCoins() == null){
            playerInfo.setCoins(BigDecimal.valueOf(gameConfiguration.getDifficultyLevel().getInitialCoins()));
            return playerInfo.getCoins();
        }
        return playerInfo.getCoins();
    }

    public String getUserName(){
        return playerInfo.getName();
    }

    public void addPoints(int points){
        playerInfo.setPoints(playerInfo.getPoints() + points);
    }

    public void setPlayerName(String name){
        playerInfo.setName(name);
    }

    public GameConfiguration getGameConfiguration() {
        return gameConfiguration;
    }

    public void setGameConfiguration(GameConfiguration gameConfiguration) {
        this.gameConfiguration = gameConfiguration;
    }

    public DifficultyLevel getDifficultyLevel(){
        return this.gameConfiguration.getDifficultyLevel();
    }

    public List<ResourceTower> getActiveTowers() {
        return allTower.stream().filter(item-> item.getState() == TowerState.ACTIVE).collect(Collectors.toList());
    }

    public List<ResourceTower> getTowers() {
        return allTower;
    }


    public List<Upgrade> getUpgrades() {
        return upgrades;
    }

    public void setTowers(List<ResourceTower> allTower) {
        this.allTower = allTower;
    }

    public Integer getGameRound() {
        return gameRound;
    }

    public Integer getMaxGameRound(){
        return getGameConfiguration().getNumberOfRounds();
    }

    /**
     * Increments the current game round by one.
     */
    public void roundUp() {
        gameRound ++;
    }

    public void setTowerState(ResourceTower resourceTower, TowerState state) {
        allTower.stream().filter(item-> Objects.equals(resourceTower.getId(),item.getId())).findFirst().ifPresent(resourceTower1 -> resourceTower1.setState(state));
    }

    public boolean hasNextRound() {
        return gameRound <= getMaxGameRound();
    }

    public void removeTower() {
    }
}
